package cn.layfolk.seckill.service.impl;

import cn.layfolk.daimao.consts.ErrorCodeEnum;
import cn.layfolk.daimao.consts.MQConstans;
import cn.layfolk.daimao.exception.MessageCenterException;
import cn.layfolk.daimao.vo.TUser;
import cn.layfolk.seckill.domain.TOrderInfo;
import cn.layfolk.seckill.mapper.TOrderInfoMapper;
import cn.layfolk.seckill.redis.SeckillRedisKey;
import cn.layfolk.seckill.service.TOrderInfoService;
import cn.layfolk.seckill.service.TSeckillGoodsService;
import cn.layfolk.seckill.service.TSeckillOrderService;
import cn.layfolk.seckill.util.IdGenerateUtil;
import cn.layfolk.seckill.vo.SeckillGoodsVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2021-01-10
 */
@Service
public class TOrderInfoServiceImpl extends ServiceImpl<TOrderInfoMapper, TOrderInfo> implements TOrderInfoService {

    @Autowired
    private TSeckillGoodsService seckillGoodsService;

    @Autowired
    private TSeckillOrderService seckillOrderService;

    @Autowired
    private TOrderInfoMapper orderInfoMapper;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 获取订单信息
     */
    @Override
    public TOrderInfo findById(String orderNo) {
        //获取用户信息
        //用户不等于null
        TUser user = null;

        //根据订单编号，以及用户id获取订单信息
        QueryWrapper<TOrderInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no", orderNo)
                .eq("user_id", user.getId());

        return orderInfoMapper.selectOne(wrapper);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String doSeckill(SeckillGoodsVo vo, Long userId) {
        //1.扣减库存
        Integer ret = seckillGoodsService.decrStockCount(vo);
        if (ret <= 0) {
            throw new MessageCenterException(ErrorCodeEnum.OUT_OF_STOCK_ERROR);
        }
        //2.创建基础订单信息
        String orderNo = this.createOrder(vo, userId);
        //3.创建秒杀订单
        seckillOrderService.create(orderNo, userId, vo.getId());
        //4.返回创建订单号
        return orderNo;

    }

    @Override
    public String doSeckill(Long seckillId, Long userId) {
        SeckillGoodsVo vo = seckillGoodsService.findByIdInCache(seckillId);
        return doSeckill(vo, userId);
    }

    @Override
    public void handleCreateOrderFailed(Long seckillId) {
        //1.查询mysql中的库存
        SeckillGoodsVo vo = seckillGoodsService.findById(seckillId);
        if (vo != null) {
            //2.将mysql中的库存同步到Redis中
            stringRedisTemplate.opsForHash().put(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(""),
                    seckillId + "", vo.getStockCount() + "");
            //3.发送清除本地售完标记的消息
            rocketMQTemplate.syncSend(MQConstans.CLEAR_STOCK_OVER_MAP_DEST, seckillId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void checkOrderTimeout(String orderNo, Long seckillId) {
        //1.查出订单信息
        QueryWrapper<TOrderInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no", orderNo);
        TOrderInfo orderInfo = orderInfoMapper.selectOne(wrapper);
        if (orderInfo == null) {
            return;
        }

        //2. 判断订单状态，是否已支付
        if (!TOrderInfo.STATUS_ACCOUNT_PAID.equals(orderInfo.getStatus())) {
            //3. 如果订单为未支付，进行订单回补
            //4. 将数据库的库存进行+1
            seckillGoodsService.incrStockCount(seckillId);
            // 将订单状态设置为已取消
            orderInfoMapper.updateStatus(orderNo, TOrderInfo.STATUS_TIMEOUT);
            //5. 将Redis 的库存还原为数据库中的库存
            SeckillGoodsVo vo = seckillGoodsService.findById(seckillId);
            stringRedisTemplate.opsForHash().put(SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(""),
                    seckillId + "", vo.getStockCount() + "");
            //6. 发送广播消息，通知所有节点清除自身的本地售完标记
            rocketMQTemplate.syncSend(MQConstans.CLEAR_STOCK_OVER_MAP_DEST, seckillId);
        }
    }

    @Override
    public void updatePaySuccess(String orderNo) {
        int ret  = orderInfoMapper.paySuccess(orderNo);
        // 根据结果做业务逻辑
        System.out.println("更新订单支付成功:"+ret);
    }

    private String createOrder(SeckillGoodsVo vo, Long userId) {
        TOrderInfo order = new TOrderInfo();
        order.setUserId(userId);
        order.setStatus(TOrderInfo.STATUS_ARREARAGE);
        order.setDeliveryAddrId(1L);
        order.setGoodCount(1);
        order.setGoodId(vo.getGoodId());
        order.setGoodImg(vo.getGoodImg());
        order.setGoodName(vo.getGoodName());
        order.setGoodPrice(vo.getGoodPrice());
        order.setSeckillPrice(vo.getSeckillPrice());
        String orderNo = IdGenerateUtil.get().nextId() + "";
        order.setOrderNo(orderNo);
        //保存订单
        orderInfoMapper.insert(order);
        return orderNo;
    }

}
